package com.bayihouse.excel.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.metadata.CellExtra;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.read.listener.ReadListener;
import com.bayihouse.common.ErrorCode;
import com.bayihouse.exception.BusinessException;
import com.bayihouse.model.entity.*;
import com.bayihouse.model.enums.RoomRoleEnum;
import com.bayihouse.model.excel.ExcelRoom;
import com.bayihouse.utils.*;
import jnr.ffi.annotations.In;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Data
@NoArgsConstructor
@AllArgsConstructor
public class ExcelRoomListener implements ReadListener<ExcelRoom> {

    private static final int BATCH_COUNT = 1000;

    private String filePath;

    private String fileName;
    private Netobject newNetObject;


    private static final String businessStr = "商业区";

    private Set<Netobject> netobjectSet;

    private ExcelCommunityUtils excelCommunityUtils;


    public ExcelRoomListener(ExcelCommunityUtils excelCommunityUtils) {
        this.excelCommunityUtils = excelCommunityUtils;
    }


    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        ReadListener.super.onException(exception, context);
    }

    @Override
    public void invokeHead(Map<Integer, ReadCellData<?>> headMap, AnalysisContext context) {
        ReadListener.super.invokeHead(headMap, context);
    }

    @Override
    public void invoke(ExcelRoom excelRoom, AnalysisContext analysisContext) {
        String roomCommunity = excelRoom.getCommunity();
        if (StringUtils.isNotBlank(roomCommunity)) {
            int setSize = netobjectSet.size();
            Netobject netobject = new Netobject();
            netobject.setName(roomCommunity);
            netobjectSet.add(netobject);
            if (setSize != netobjectSet.size()) {
                excelCommunityUtils.getNetObjectService().save(netobject);
                newNetObject = netobject;
                newNetObject.initT();
            } else {
                newNetObject = excelCommunityUtils.getNetobject(netobjectSet, roomCommunity);
            }
        }
        List<Community> communityList = newNetObject.getTlist();
        Room room = new Room();
        BeanUtils.copyProperties(excelRoom, room);
        String rentStatus = excelRoom.getRentStatus();
        String rentChannel = excelRoom.getRentChannel();
        Integer category = room.getCategory();
        String label = "[";
        String initStatus = label;
        if (StringUtils.isNotBlank(rentStatus)) {
            label += "\"" + rentStatus + "\"";
        }
        if (StringUtils.isNotBlank(rentChannel)) {
            if (!label.equals(initStatus)) {
                label += ",";
            }
            label += "\"" + rentChannel + "\"";
        }
        label += "]";
        room.setLabel(label);

        Occupant landlord = new Occupant();
        landlord.setName(excelRoom.getLandlord());
        landlord.setRole("本人");
        try {
            landlord.setBirthday(MyDateUtils.getBirthday(excelRoom.getIdentity()));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        landlord.setIdentity(excelRoom.getIdentity());
        landlord.setSex((excelRoom.getIdentity().charAt(16) - '0') % 2);
        landlord.setTelephone(excelRoom.getTelephone());


        String address = excelRoom.getAddress();
        try {
            if (StringUtils.isNotBlank(address)) {
                if (!AddressUtils.isBusinessUsing(address)) {
                    String[] nowAddressArrayLiving = AddressUtils.getNowAddressArrayLiving(address);
                    String communityAddress = nowAddressArrayLiving[0];
                    String communityName = nowAddressArrayLiving[1];
                    String houseName = nowAddressArrayLiving[2];
                    String unitName = nowAddressArrayLiving[3];
                    room.setName(nowAddressArrayLiving[4]);
                    Community resCommunity = excelCommunityUtils.findCommunity(communityList, communityName, communityAddress, RoomRoleEnum.LIVING_USING, newNetObject);
                    House resHouse = excelCommunityUtils.findHouse(resCommunity, houseName);
                    Unit resUnit = excelCommunityUtils.findUnit(resHouse, unitName);
                    MyObjectUtils.addObject(resUnit.getTlist(), room);
                } else {
                    String[] nowAddressArrayBusiness = AddressUtils.getNowAddressArrayBusiness(address);
                    String communityName = businessStr;
                    room.setName(nowAddressArrayBusiness[2]);
                    Community resCommunity = excelCommunityUtils.findCommunity(communityList, communityName, communityName, RoomRoleEnum.BUSINESS_USING, newNetObject);
                    MyObjectUtils.addObject(resCommunity.getVlist(), room);
                }
            } else {
                throw new BusinessException(ErrorCode.OPERATION_ERROR, "excel表格中的地址信息是空的");
            }
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
            Community resCommunity = excelCommunityUtils.findCommunity(communityList, businessStr, businessStr, RoomRoleEnum.BUSINESS_USING, newNetObject);
            room.setName(address);
            MyObjectUtils.addObject(resCommunity.getVlist(), room);
        }
        room.setAddress(address);
        room.setFather(landlord);
        room.initT();
    }


    @Override
    public void extra(CellExtra extra, AnalysisContext context) {
        ReadListener.super.extra(extra, context);
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        saveData();
    }


    @Override
    public boolean hasNext(AnalysisContext context) {
        return ReadListener.super.hasNext(context);
    }


    public void saveData() {
        List<Community> communityList = MyObjectUtils.dealFlatStreamToList(netobjectSet.stream().map(Netobject::getTlist));
        SqlUtils.insertDataBase(communityList, excelCommunityUtils.getCommunityService());
        communityList.stream().forEach(object -> {
            object.setTId();
            object.setVId();
            if (MyObjectUtils.isArraysEmpty(object.getTlist())) return;
            object.getTlist().forEach(house -> {
                house.getTlist().stream().forEach(unit -> {
                    unit.getTlist().forEach(room -> {
                        room.setCommunityId(object.getId());
                    });
                });
            });
        });
        List<House> houseList = MyObjectUtils.dealFlatStreamToList(communityList.stream().filter(community -> {
            return community.getTlist() != null;
        }).map(Community::getTlist));
        SqlUtils.insertDataBase(houseList, excelCommunityUtils.getHouseService());
        houseList.stream().forEach(object -> {
            object.setTId();
        });
        List<Unit> unitList = MyObjectUtils.dealFlatStreamToList(houseList.stream().map(House::getTlist));
        SqlUtils.insertDataBase(unitList, excelCommunityUtils.getUnitService());
        unitList.stream().forEach(object -> {
            object.setTId();
        });
        Stream<List<Room>> businessRoomStream = communityList.stream().filter(community -> {
            boolean arraysEmpty = MyObjectUtils.isArraysEmpty(community.getVlist());
            return !arraysEmpty;
        }).map(Community::getVlist);
        Stream<List<Room>> listStream = unitList.stream().map(Unit::getTlist);
        Stream<List<Room>> sumStream = MyObjectUtils.mergeTwoStream(listStream, businessRoomStream);
        List<Room> roomList = MyObjectUtils.dealFlatStreamToList(sumStream);
        SqlUtils.insertDataBase(roomList, excelCommunityUtils.getRoomService());
        roomList.stream().forEach(object -> {
            object.setFId();
        });
        List<Occupant> landlordList = roomList.stream().map(Room::getFather).collect(Collectors.toList());
        SqlUtils.insertDataBase(landlordList, excelCommunityUtils.getOccupantService());
    }


}
